#ifndef RANDLIB_MYRANDLIB_H_             
#define RANDLIB_MYRANDLIB_H_


#include <cassert>
#include<stdlib.h>
#include <vector>
#include <algorithm>

typedef unsigned int uint32_t;

/**
 * @brief 是否命中概率
 * @param x 概率为x/n
 * @param n 概率的基数
 * @return true表示命中概率
 */
inline bool is_rand_hit(int x, int n = 100)
{
    if (n <= 0) return false;
    int r = rand() % n;
    return r < x;
}

/**
 * @brief 从一个闭区间中随机一个数
 * @param a 左界
 * @param b 右界
 * @return 随机的结果
 */
inline int rand_with_range(int a, int b)
{
    //确保a < b
    if (a > b) {
        int tmp = a;
        a = b;
        b = tmp;
    }

    //包含a和b
    int r = rand() % (b - a + 1);
    return r + a;
}

/**
 * @brief 根据概率数组，返回输出下标
 * @param arr 概率数组，会自动根据提供的数据计算概率,只支持整数
 * @param count 行的数量，即有多少个
 * @return 符合概率的数组下标
 */
inline int rand_with_rate_array_by_step(int* arr, int count, int step = 1)
{
    // 默认的输出
    uint32_t outid = 0;

    uint32_t sum = 0; // 用于概率的统计
    int i;
    for (i = 0; i < count; i++) {
        sum += *(arr+step*i);
    }
    assert(sum != 0);
    int r = rand() % sum;

    sum = 0;
    for (i = 0; i < count; i++) {
        sum += *(arr+step*i);

        // 达到指定的概率
        if (r < (int) sum) {
            outid = i;
            break;
        }
    }
    return outid;

}

/**
 * @brief 根据概率数组，返回输出下标
 * @param arr 概率数组，会自动根据提供的数据计算概率,只支持整数
 * @param count 行的数量，即有多少个
 * @return 符合概率的数组下标
 */
inline int rand_with_rate_array(int arr[], int count)
{
    return rand_with_rate_array_by_step(arr, count, 1);
}

/**
 * @brief 根据输出outid及概率的数组，返回输出outid
 * @param arr 概率数组，会自动根据提供的数据计算概率,只支持整数
 * @param count 行的数量，即有多少个
 * @return 符合概率的结果
 */
inline int rand_with_value_rate_array(int arr[][2], int count)
{
    // 默认的输出
    uint32_t outid = rand_with_rate_array_by_step((int*)arr, count, 2);
    outid = arr[outid][1];
    return outid;
}

/**
 * @brief 从指定数据status的前n位中随机出一个清位的位置
 * @param status 数据
 * @param n 前几位
 * @return 符合概率的位下标，从1开始
 */
inline int rand_bit_off_index(int status, int start, int end)
{
    assert((end - start) > 0);
    int result = 0;
    int vec[32];
    int size = 0;
    for (int i = start; i < end; ++i) {
        //找到清位
        if (!(status & (1 << i))) {
            vec[size++] = i + 1;
        }
    }
    assert(size >0);
    if (size > 0) {
        result = vec[rand() % size];
    }
    return result;
}

/**
 * @brief 从指定数据status的前n位中随机出一个清位的位置
 * @param status 数据
 * @param start 开始的位置，从0开始
 * @param end 结束的下一个位置，从0开始
 * @return 符合概率的位下标，从1开始
 */
inline int rand_bit_off_index(int status, int n)
{
    return rand_bit_off_index(status, 0, n);
}

/**
 * @brief 从指定数据status的前n位中随机出一个置位的位置
 * @param status 数据
 * @param start 开始的位置，从0开始
 * @param end 结束的下一个位置，从0开始
 * @return 符合概率的位下标，从1开始
 */
inline int rand_bit_on_index(int status, int start, int end)
{
    //
    status = ~status;
    return rand_bit_off_index(status, start, end);
}


/**
 * @brief 从指定数据status的前n位中随机出一个置位的位置
 * @param status 数据
 * @param n 前几位
 * @return 符合概率的位下标，从1开始
 */
inline int rand_bit_on_index(int status, int n)
{
    return rand_bit_on_index(status, 0, n);
}


/**
 * @brief 从一个区间随机出n个结果，保存到vector中
 * @param n 要随机的结果数量
 * @param start 区间的开始，含
 * @param end 区间的结束，含
 * @param result 引用，随机的结果
 * @return 0
 */
inline int rand_n_result_from_range(int n, int start, int end,
        std::vector<int>& result)
{
    result.clear();
    int count = end - start + 1;
    for(int i = start; i <= end; i++) {
        result.push_back(i);
    }
    random_shuffle(result.begin(), result.end());
    if (n <= count) { // 如果结果小于区间的数量
        result.resize(n);
	return 0;
    }
    return 1; // 结果的个数小于要求的个数
}

/**
 * @brief 从一个数组中随机出n个结果，保存到vector中
 * @param n 要随机的结果数量
 * @param arr 数组指针
 * @param count 数组的大小
 * @param result 引用，随机的结果
 * @return 0
 */
inline int rand_n_result_from_array(int n, int* arr, int count,
        std::vector<int>& result)
{
    result.clear();
    for(int i = 0; i < count; i++) {
        result.push_back(arr[i]);
    }
    random_shuffle(result.begin(), result.end());
    if (n <= count) {
        result.resize(n);
        return 0;
    }
    return 1; // 结果小于要求的数量
}




#endif // RANDLIB_MYRANDLIB_H_
